iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
自我挑戰組

<< 測試魔法 >> 這能動嗎?不然就測測看好了!系列 第 9

情境練習:打勾才能按確認按鈕

  • 分享至 

  • xImage
  •  

前情提要

「今天來考試吧!」艾草緩緩開口。

「誒 !!? 考試不是要提前說嗎?還是可以翻書考?」

「你要翻什麼書?」艾草心裡默默唸叨:我可不記得我有勤勞到出教材。

「口頭禪而已,沒事啦!」

「好啦,不用太緊張就是一個小練習而已。只是複習之前有講解過的部分而已啦 ~~」

我害怕的想著:怎麼感覺像從小到大老師口中說的這次考試範圍書裡都有,但考出來都不懂呢 …

https://ithelp.ithome.com.tw/upload/images/20220924/20139066WEgcujDlA0.png


今天要來做一個測試的小練習,是撰寫常見的情境,在註冊時常常會有需要打勾確認同意網站相關規定後,註冊按鈕才會從 disabled 狀態切換成可點擊。

https://ithelp.ithome.com.tw/upload/images/20220924/20139066zGJQuYprWq.png

正好可以透過昨天有學習到的 Jest DOM 來協助判斷。

首先,先撰寫一個元件 Form , Form 會有 checkbox 跟 button ,且 Form 會使用 React hook useState 來管理是否點擊的狀態,當 checkbox 點擊時我們會透過 setIsChecked 將 checkbox 轉為 true 或 false ,並使用此狀態綁定 button 的 disabled 屬性。

import { useState } from "react";

const Form = () => {
    const [isChecked, setIsChecked] = useState(false);
    return (
      <form>
        <label htmlFor="agreeRules">
        <input
          type="checkbox"
          id="agreeRules"
          onChange={(e) => setIsChecked(e.target.checked)}
        />
        確認同意網站規則嗎?
        </label>
        <button type="button" disabled={!isChecked}>
          送出
        </button>
      </form>
    );
  };

  export default Form;

接下來在與 Form 同一層級的地方撰寫 Form.test.js 檔案:

並引入 jest 及 React Testing Library 及 Jest Dom ,最後也別忘記引入 Form 元件:

import "jest";
import React from 'react';
import { render, fireEvent, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Form from "./test";

接下來透過 Jest 的 describe 包覆要測試的內容:

describe('Click the checkbox to change the disabled property of the button', () => {

})

在測試裡,可以先撰寫一開始會顯示的情形:

describe('Click the checkbox to change the disabled property of the button', () => {
  test('Unable to press the button at first' ,() => {
    render(<Form />);
    expect(screen.getByRole('button')).toBeDisabled();
  })
})

接下來透過 React Testing Library 的 fireEvent 模擬點擊行為 !

fireEvent 可以幫忙觸發事件,依據官網的使用方式如下:

fireEvent[eventName](node: HTMLElement, eventProperties: Object)

[eventName] 的地方指的是 click 、 change 等操作事件的名稱,而可帶入的兩個參數分別為:

  1. 觸發的目標元素
  2. 觸發時給定的值

測試事件為 click 所以只需要給定第一個參數即可,並透過 getByRole 選定 checkbox 角色,最後透過 .not.toBeDisabled() 進行斷言:

describe('Click the checkbox to change the disabled property of the button', () => {
  test('Unable to press the button at first' ,() => {
    render(<Form />);
    expect(screen.getByRole('button')).toBeDisabled();
  })
  test('The button can be turned on when the checkbox is checked' ,() => {
    render(<Form />);
    fireEvent.click(screen.getByRole('checkbox'));
    expect(screen.getByRole('button')).not.toBeDisabled();
  })
})

如果想使用 toBeEnabled() 也是可以的!

test('The button can be turned on when the checkbox is checked' ,() => {
  render(<Form />);
  fireEvent.click(screen.getByRole('checkbox'));
  expect(screen.getByRole('button')).toBeEnabled();
})

最後,也可以測試點擊兩次後按鈕是否會恢復禁用:

test('Clicking the checkbox twice disables the button',() => {
   render(<Form />);
   fireEvent.click(screen.getByRole('checkbox'));
   expect(screen.getByRole('button')).not.toBeDisabled();
   fireEvent.click(screen.getByRole('checkbox'));
   expect(screen.getByRole('button')).toBeDisabled();
})

測試點擊一次及點擊兩次的情況也可以整合成同一個測試即可,這次為了練習先將他們分開撰寫,最後就完成這次測試練習了!

import "jest";
import React from 'react';
import { render, fireEvent, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Form from "./test";

describe('Click the checkbox to change the disabled property of the button', () => {
  test('Unable to press the button at first' ,() => {
    render(<Form />);
    expect(screen.getByRole('button')).toBeDisabled();
  })
  test('The button can be turned on when the checkbox is checked' ,() => {
    render(<Form />);
    fireEvent.click(screen.getByRole('checkbox'));
    expect(screen.getByRole('button')).toBeEnabled();
  })
  test('Clicking the checkbox twice disables the button',() => {
    render(<Form />);
    fireEvent.click(screen.getByRole('checkbox'));
    expect(screen.getByRole('button')).not.toBeDisabled();
    fireEvent.click(screen.getByRole('checkbox'));
    expect(screen.getByRole('button')).toBeDisabled();
  })
})

下一篇會提到另一個可以替代 fireEvent 的函式庫 @testing-library/user-event


參考文件

Testing React with Jest and React Testing Library (RTL)
https://ithelp.ithome.com.tw/articles/10248517


上一篇
Jest DOM 實用匹配器
下一篇
用 User Event 模擬使用者操作
系列文
<< 測試魔法 >> 這能動嗎?不然就測測看好了!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言